package hn.cch.grammar.security;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class Rsa2Util {




    private static String algorithm = "SHA256withRSA";

    private static final String keyalg = "RSA";
    private static final int keylen = 2048;

    public static final String pubkey = "pubkey";
    public static final String prikey = "prikey";


    public static Map<String, byte[]> getKeyMap() {

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyalg);
            keyPairGenerator.initialize(keylen);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            Map<String, byte[]> keymap = new HashMap<>();
            keymap.put(pubkey, publicKey.getEncoded());
            keymap.put(prikey, privateKey.getEncoded());
            return keymap;
        } catch (NoSuchAlgorithmException e) {
            System.out.println(e.getMessage());
        }
        return null;
    }


    public static byte[] sign(byte[] keys, byte[] data) {
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keys);
            KeyFactory keyFactory = KeyFactory.getInstance(keyalg);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

            Signature signature = Signature.getInstance(algorithm);
            signature.initSign(privateKey);
            signature.update(data);
            byte[] sign = signature.sign();
            return sign;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new byte[0];
        }

    }

    public static boolean verify(byte[] keys, byte[] data, byte[] sign) {
        try {
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keys);
            KeyFactory keyFactory = KeyFactory.getInstance(keyalg);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);


            Signature signature = Signature.getInstance(algorithm);
            signature.initVerify(publicKey);
            signature.update(data);
            boolean verify = signature.verify(sign);
            return verify;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return false;
        }

    }


    public static void main(String[] args) {

        byte[] data = "1234567890qwertyuiopasdfghjklzxcvbnm".getBytes(StandardCharsets.UTF_8);


        Map<String, byte[]> keymap = Rsa2Util.getKeyMap();
        System.out.println(new String(Base64Util.encode(keymap.get(Rsa2Util.pubkey))));
        System.out.println(new String(Base64Util.encode(keymap.get(Rsa2Util.prikey))));
        byte[] sign = Rsa2Util.sign(keymap.get(Rsa2Util.prikey), data);
        boolean verify = Rsa2Util.verify(keymap.get(Rsa2Util.pubkey), data, sign);

        // String pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2CfthXK0pE7sEbnyc90DDPMePbrNLdXwj2EnLQaAMj4VCTYZsFCkUco3eywM9/LbGVPEW3tfpwO9R/lJtzoWLzLmMIWkMBzz5byd0KryRh8f+CwVE5oFy/FDPdOFFjjW+I0V6emFT2lO+J12FtPG0Lwp5vyU4po4rzvr/s3ZClQIDAQAB";
        // String prikey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALYJ+2FcrSkTuwRufJz3QMM8x49us0t1fCPYSctBoAyPhUJNhmwUKRRyjd7LAz38tsZU8Rbe1+nA71H+Um3OhYvMuYwhaQwHPPlvJ3QqvJGHx/4LBUTmgXL8UM904UWONb4jRXp6YVPaU74nXYW08bQvCnm/JTimjivO+v+zdkKVAgMBAAECgYA1+xvKMVs/9RPeKo1VVpSj0KA0zlToqXwYfQjU9y7oyp5vnOGhpxDPeXDMglMBzLC+e23KpGZOcOIG5G25FibPX0OL0TPJU1tf+BBK2DBysDHpf5htRr05Fum3hbdwsjYaprF3nCSpS1Xs0a+MolcoR3GJQJLxD7onNI9psxN8+QJBAO7qgX+ksHrNHD0z4WcH9MqMntbIfdiqn4yC3ZKF+ym0yA6nFT9l8s9J38CCM2xFUMD23QsgTtqIo9snAdfXawMCQQDDDk8zGC6qwGKQWB9WkKpTNZszDYdISx4ZK2nKV9V5uk3hPkhjGkozmDz8z5fqrNP/KgXmT3MgrigmiQI5jZyHAkEAqdoONrDexm8LpHc9yAHgBh/yzL+8uEyVIU/oNkMKTJw5njEq6eeQt83NRQ9Lf63Hu2fFviM57CM4WpVguhJsAQJAJn04W5i1/LOhv2HkLSy2r1ywl05gF3/bHJRYd7kFQtPkckHb/tI9OhkcT7aW/5PC8WLVbzDWQuiau5/ldH3hGQJAVZad16PpeoQCHhC4P5pI9bDoZ0TNrEPAlYVavzejmaEHXfEOwmtKq+uyeRsgqAMPSff62qhNo517zmeSpz1j2g==";
        // byte[] sign = Rsa2Util.sign(Base64Util.decode(StringUtil.toBytes(prikey)), data);
        // boolean verify = Rsa2Util.verify(Base64Util.decode(StringUtil.toBytes(pubkey)), data, sign);

        System.out.println(new String(Base64Util.encode(sign)));

        System.out.println(verify);


    }
}

